package com.wms.ymcc.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.alipay.easysdk.factory.Factory;
import com.alipay.easysdk.kernel.util.ResponseChecker;
import com.alipay.easysdk.payment.page.models.AlipayTradePagePayResponse;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.wms.ymcc.api.OrderAPI;
import com.wms.ymcc.domain.AlipayInfo;
import com.wms.ymcc.domain.PayFlow;
import com.wms.ymcc.domain.PayOrder;
import com.wms.ymcc.dto.AlipayNotifyDto;
import com.wms.ymcc.dto.PayApplyDto;
import com.wms.ymcc.exception.GlobalBaseException;
import com.wms.ymcc.mapper.PayOrderMapper;
import com.wms.ymcc.result.JSONResult;
import com.wms.ymcc.service.IAlipayInfoService;
import com.wms.ymcc.service.IPayFlowService;
import com.wms.ymcc.service.IPayOrderService;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.alibaba.fastjson.JSONObject;
import com.alipay.easysdk.factory.Factory;
import com.alipay.easysdk.kernel.Config;
import com.alipay.easysdk.kernel.util.ResponseChecker;
import com.alipay.easysdk.payment.page.models.AlipayTradePagePayResponse;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author wms
 * @since 2025-06-23
 */
@Service
@Slf4j
public class PayOrderServiceImpl extends ServiceImpl<PayOrderMapper, PayOrder> implements IPayOrderService {

    @Autowired
    private IAlipayInfoService alipayInfoService;

    @Autowired
    private PayOrderMapper payOrderMapper;

    @Autowired
    private IPayFlowService payFlowService;

    @Autowired
    private OrderAPI orderAPI;

    /**
     * 支付事务
     * @param alipayNotifyDto
     * @return
     */
    @Override
    public String payNotify(AlipayNotifyDto alipayNotifyDto) {

        // 1. 校验  略

        try {
            // 2. 验签
            // 获取map
            String jsonString = JSONObject.toJSONString(alipayNotifyDto);
            Map<String,String> map = JSONObject.parseObject(jsonString, Map.class);
            Boolean b = Factory.Payment.Common().verifyNotify(map);
            if(!b){ // 验签失败
                log.error("验签失败");
                return "error";
            }

            // 验签成功
            /**
             * 1. 商家需要验证该通知数据中的 out_trade_no 是否为商家系统中创建的订单号。
             * 2. 判断 total_amount 是否确实为该订单的实际金额（即商家订单创建时的金额）。
             * 3. 校验通知中的 seller_id（或者 seller_email）是否为 out_trade_no 这笔单据的对应的操作方（有的时候，一个商家可能有多个 seller_id/seller_email）。
             * 4. 验证 app_id 是否为该商家本身。
             */

            // 3. 更新表， t_course_order, t_pay_order
            //TODO 添加t_course_order
            // 4. 添加操作   t_pay_flow，  t_course_user_learn(哪个用户购买了那个课程。)

            // 更新t_pay_order  1
            String orderNo = alipayNotifyDto.getOut_trade_no();
            payOrderMapper.updateByOrderNo(orderNo);

            // 添加t_pay_flow
            PayFlow payFlow = new PayFlow();
            Date date = new Date();
            payFlow.setNotifyTime(date);
            payFlow.setSubject(alipayNotifyDto.getSubject());
            payFlow.setOutTradeNo(orderNo);
            payFlow.setTotalAmount(new BigDecimal(alipayNotifyDto.getTotal_amount()));
            payFlow.setTradeStatus(alipayNotifyDto.getTrade_status());
            payFlow.setPaySuccess(true);
            payFlowService.insert(payFlow);

            // 更新表， t_course_order
            orderAPI.updateCourseOrderByOrderNo(orderNo);

            // 其他业务。。。。。。
            return "success";

        } catch (Exception e) {
            e.printStackTrace();
            return "error";
        }
    }


    /**
     * 支付单查询校验
     * @param orderNo
     * @return
     */
    @Override
    public JSONResult checkPayOrder(String orderNo) {
        //TOOD 支付单查询校验
        Wrapper<PayOrder> ww = new EntityWrapper<>();
        ww.eq("order_no",orderNo);
        PayOrder payOrder = selectOne(ww);
        if(payOrder==null){
            return JSONResult.error();
        }
        return JSONResult.success();
    }

    /**
     * 支付申请
     * @param payApplyDto
     * @return
     */
    @Override
    public String apply(PayApplyDto payApplyDto) {
        // 1. 设置参数（全局只需设置一次）
        Factory.setOptions(getOptions());
        try {
            Integer payType = payApplyDto.getPayType();
            String orderNo = payApplyDto.getOrderNo();
            String callUrl = payApplyDto.getCallUrl();

            // 根据订单编号查询支付单信息
            Wrapper<PayOrder> ww = new EntityWrapper<>();
            ww.eq("order_no", orderNo);
            PayOrder payOrder = selectOne(ww);

            // 判断支付状态是否是未支付状态
            if (payOrder.getPayStatus() == 0) {
                //可以抽离出支付方，微信 支付宝 银联
                AlipayTradePagePayResponse alipayTradePagePayResponse = Factory.Payment.Page().pay(
                        payOrder.getSubject(),
                        payOrder.getOrderNo(),
                        payOrder.getAmount().toString(),
                        callUrl);  // 成功的页面地址
                // 3. 处理响应或异常
                if (ResponseChecker.success(alipayTradePagePayResponse)) {
                    return alipayTradePagePayResponse.getBody(); // form表单
                }
            }
            return "支付失败";
        } catch (Exception e) {
            e.printStackTrace();
            throw new GlobalBaseException("支付失败");
        }
    }


    /**
     * 获取获取与支付宝交互的配置参数
     * @return
     */
    private Config getOptions() {

        // 从数据库查询支付参数
        List<AlipayInfo> alipayInfos = alipayInfoService.selectList(null);
        AlipayInfo alipayInfo = alipayInfos.get(0);

        Config config = new Config();
        config.protocol = alipayInfo.getProtocol();
        config.gatewayHost = alipayInfo.getGatewayHost();
        config.signType = alipayInfo.getSignType();  // 签名类型
        config.appId = alipayInfo.getAppId();
        // 为避免私钥随源码泄露，推荐从文件中读取私钥字符串而不是写入源码中
        config.merchantPrivateKey = alipayInfo.getMerchantPrivateKey();

        config.alipayPublicKey = alipayInfo.getAlipayPublicKey();
        //可设置异步通知接收服务地址
        config.notifyUrl = alipayInfo.getNotifyUrl();
        return config;
    }
}
